home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / capturing / hacktv / common.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  17.0 KB  |  585 lines

  1. /*
  2.     File:        Common.c
  3.  
  4.     Contains:    HackTV cross-platform common code
  5.  
  6.     Written by:    Gary Woodcock
  7.     Updated by: Brian Friedkin
  8.             
  9.     Copyright:    © 1992-1998 by Apple Computer, Inc.
  10. */
  11. #include <QTML.h>
  12. #include <Endian.h>
  13. #include <Menus.h>
  14. #include <Printing.h>
  15. #include <Script.h>
  16. #include <Scrap.h>
  17. #include <QuickTimeComponents.h>
  18. #include "Globals.h"
  19. #include "Common.h"
  20.  
  21. // Disable warnings associated with "\p" strings
  22. #if TARGET_OS_WIN32
  23. #pragma warning(disable: 4129)
  24. #endif
  25.  
  26. static OSErr XorRectToRgn(Rect *srcRectA, Rect *srcRectB, RgnHandle *destRgn);
  27.  
  28. /* ---------------------------------------------------------------------- */
  29.  
  30. void InitializeSequenceGrabber(void)
  31. {
  32.     ComponentDescription    theDesc;
  33.     ComponentResult            result = noErr;
  34.     GrafPtr                    savedPort;
  35.     Component                sgCompID;
  36.     
  37.     gQuitFlag = false;
  38.     gSeqGrabber = 0L;
  39.     gVideoChannel = 0L;
  40.     gSoundChannel = 0L;
  41.     gMonitorPICT = nil;
  42.     gPrintRec = (THPrint) NewHandleClear (sizeof (TPrint));
  43.     
  44.     // Find and open a sequence grabber
  45.     theDesc.componentType = SeqGrabComponentType;
  46.     theDesc.componentSubType = 0L;
  47.     theDesc.componentManufacturer = 'appl';
  48.     theDesc.componentFlags = 0L;
  49.     theDesc.componentFlagsMask = 0L;    
  50.     sgCompID = FindNextComponent (nil, &theDesc);
  51.     if (sgCompID != 0L)
  52.         gSeqGrabber = OpenComponent (sgCompID);
  53.     
  54.     // If we got a sequence grabber, set it up
  55.     if (gSeqGrabber != 0L)
  56.     {
  57.         // Get the monitor
  58.         CreateMonitorWindow();
  59.         if (gMonitor != nil)
  60.         {
  61.             // Display the monitor window
  62.             GetPort (&savedPort);
  63.             MacSetPort (gMonitor);
  64.             MacMoveWindow(gMonitor, 10, 30 + GetMBarHeight(), 0);
  65.             MacShowWindow (gMonitor);        
  66.  
  67.             // Initialize the sequence grabber
  68.             result = SGInitialize (gSeqGrabber);
  69.             if (result == noErr)
  70.             {
  71.                 result = SGSetGWorld (gSeqGrabber, (CGrafPtr) gMonitor, nil);
  72.                 
  73.                 // Get a video channel
  74.                 result = SGNewChannel (gSeqGrabber, VideoMediaType, &gVideoChannel);
  75.                 if ((gVideoChannel != nil) && (result == noErr))
  76.                 {
  77.                     short    width;
  78.                     short    height;
  79.                     
  80.                     gQuarterSize = false;
  81.                     gHalfSize = true;
  82.                     gFullSize = false;
  83.                     
  84.                     result = SGGetSrcVideoBounds (gVideoChannel, &gActiveVideoRect);
  85.                     width = (gActiveVideoRect.right - gActiveVideoRect.left) / 2;
  86.                     height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 2;
  87.                     SizeWindow (gMonitor, width, height, false);
  88.                     
  89.                     result = SGSetChannelUsage (gVideoChannel, seqGrabPreview | seqGrabRecord | seqGrabPlayDuringRecord);
  90.                     result = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
  91.                 }
  92.                 
  93.                 // Get a sound channel
  94.                 result = SGNewChannel (gSeqGrabber, SoundMediaType, &gSoundChannel);
  95.  
  96.                 if ((gSoundChannel != nil) && (result == noErr))
  97.                 {
  98.                     if (gSoundChannel != nil)
  99.                     {
  100.                         result = SGSetChannelUsage (gSoundChannel, seqGrabPreview | seqGrabRecord);
  101.                         
  102.                         // Set the volume low to prevent feedback when we start the preview,
  103.                         // in case the mic is anywhere near the speaker.
  104.                         result = SGSetChannelVolume (gSoundChannel, 0x0010);
  105.                     }
  106.                 }
  107.                 
  108.                 // Get the alignment proc (for use when dragging the monitor)
  109.                 result = SGGetAlignmentProc (gSeqGrabber, &gSeqGrabberAlignProc);
  110.             }
  111.             
  112.             // Go!
  113.             if (result == noErr)
  114.                 result = SGStartPreview (gSeqGrabber);
  115.             MacSetPort (savedPort);
  116.         }
  117.     }
  118. }
  119.  
  120. /* ---------------------------------------------------------------------- */
  121.  
  122. // Specify and setup a file to contain this track's data
  123. static ComponentResult SetTrackFile(SGChannel theChannel, StringPtr prompt, StringPtr defaultName)
  124. {
  125.     StandardFileReply        reply;
  126.     ComponentResult        err;
  127.     SGOutput    theOutput;
  128.     AliasHandle    alias = 0;
  129.  
  130.     // Get the destination filename
  131.     StandardPutFile(prompt, defaultName, &reply);
  132.     if (!reply.sfGood)
  133.     {
  134.         err = fnfErr;
  135.         goto bail;
  136.     }
  137.  
  138.     // Make an alias from the filename
  139.     if (err = QTNewAlias(&reply.sfFile, &alias, true)) goto bail;
  140.     
  141.     // Create an output from this file
  142.     if (err = SGNewOutput(gSeqGrabber, (Handle)alias, rAliasType, seqGrabToDisk, &theOutput)) goto bail;
  143.  
  144.     // Associate this output with the specified channel
  145.     if (err = SGSetChannelOutput(gSeqGrabber, theChannel, theOutput)) goto bail;
  146.  
  147. bail:
  148.     if (alias) DisposeHandle((Handle)alias);
  149.     return err;
  150. }
  151.  
  152. /* ---------------------------------------------------------------------- */
  153.  
  154. // Record a movie
  155. void DoRecord(void)
  156. {
  157.     long    err;
  158.     StandardFileReply    reply;
  159.     
  160.     // Stop everything while the dialogs are up
  161.     SGStop(gSeqGrabber);
  162.  
  163.     // Get the destination filename
  164.     StandardPutFile("\pSave new movie file as:", "\pHack.mov", &reply);
  165.     if (!reply.sfGood)
  166.     {
  167.         err = fnfErr;
  168.         goto bail;
  169.     }
  170.     if ((err = SGSetDataOutput(gSeqGrabber, &reply.sfFile, seqGrabToDisk)))
  171.         goto bail;
  172.  
  173.     // Ask use for separate video and sound track files if requested
  174.     if (gSoundChannel && gRecordSound && gVideoChannel && gRecordVideo && gSplitTracks)
  175.     {
  176.         if ((err = SetTrackFile(gVideoChannel, "\pSave video track file as:", "\pHackVideo.trk")))
  177.             goto bail;
  178.         if ((err = SetTrackFile(gSoundChannel, "\pSave sound track file as:", "\pHackSound.trk")))
  179.             goto bail;
  180.     }
  181.  
  182.     // If not recording sound or video, then "disable" those channels
  183.     if (gSoundChannel && !gRecordSound)
  184.         SGSetChannelUsage(gSoundChannel, 0);
  185.     if (gVideoChannel && !gRecordVideo)
  186.         SGSetChannelUsage(gVideoChannel, 0);
  187.  
  188.     // Attempt to recover the preview area obscured by dialogs
  189. #if TARGET_OS_WIN32
  190.     UpdatePort(gMonitor);
  191. #endif
  192.     SGUpdate(gSeqGrabber, 0);
  193.  
  194.     // Make the movie file
  195.     DeleteMovieFile(&reply.sfFile);
  196.     if (err = CreateMovieFile(&reply.sfFile, 'TVOD', smSystemScript,
  197.         createMovieFileDontOpenFile | createMovieFileDontCreateMovie | createMovieFileDontCreateResFile,
  198.         nil, nil)) goto bail;
  199.         
  200.     FlushEvents(mDownMask+mUpMask,0);
  201.     
  202.     // Record!
  203.     if (err = SGStartRecord(gSeqGrabber))
  204.         goto bail;
  205.  
  206.     while (!Button() && (err == noErr))
  207.     {
  208.         err = SGIdle(gSeqGrabber);
  209.     }
  210.  
  211.     // If we recorded until we ran out of space, then allow SGStop to be
  212.     // called to write the movie resource.  The assumption here is that the
  213.     // data output filled up but the disk has enough free space left to
  214.     // write the movie resource.
  215.     if (!((err == dskFulErr) || (err != eofErr)))
  216.         goto bail;
  217.     err = SGStop(gSeqGrabber);
  218.     NoteAlert(kMovieHasBeenRecordedAlertID, 0);
  219.     err = SGStartPreview(gSeqGrabber);
  220.  
  221.     return;
  222.  
  223. bail:
  224.     SGPause(gSeqGrabber, false);
  225.     SGStartPreview(gSeqGrabber);
  226. }
  227.  
  228. /* ---------------------------------------------------------------------- */
  229.  
  230. void DoAboutDialog(void)
  231. {
  232.     short        itemHit;
  233.     DialogPtr    aboutDialog;
  234.  
  235.     aboutDialog = GetNewDialog(kAboutDLOGID, nil, (WindowPtr)-1L);
  236.  
  237.     // Do the boring about dialog
  238.     SetDialogDefaultItem(aboutDialog, 1);
  239.     MacShowWindow(aboutDialog);
  240.     do
  241.     {
  242.         ModalDialog(nil, &itemHit);
  243.     }
  244.     while (itemHit != 1);
  245.     DisposeDialog(aboutDialog);
  246. }
  247.  
  248. /* ---------------------------------------------------------------------- */
  249.  
  250. void DoPageSetup(void)
  251. {
  252.     PrOpen();
  253.     PrStlDialog(gPrintRec);
  254.     PrClose();
  255. }
  256.  
  257. /* ---------------------------------------------------------------------- */
  258.  
  259. void DoPrint(void)
  260. {
  261.     TPPrPort    printPort;
  262.     TPrStatus    printStatus;
  263.     ComponentResult        err;
  264.     Rect        tempRect;
  265.  
  266.     // Copy a frame from the monitor
  267.     if (gMonitorPICT != nil)
  268.         KillPicture (gMonitorPICT);
  269.     gMonitorPICT = nil;
  270.     err = SGGrabPict(gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
  271.     if ((err == noErr) && (gMonitorPICT != nil))
  272.     {
  273.         // Print it
  274.         HLock((Handle) gMonitorPICT);
  275.         PrOpen();
  276.         if (PrJobDialog (gPrintRec))
  277.         {
  278.             printPort = PrOpenDoc (gPrintRec, nil, nil);
  279.             err = PrError();
  280.             PrOpenPage (printPort, 0);
  281.             err = PrError();
  282.  
  283.             tempRect  = (**gMonitorPICT).picFrame;
  284.             tempRect.left = EndianS16_BtoN(tempRect.left);
  285.             tempRect.top = EndianS16_BtoN(tempRect.top);
  286.             tempRect.right = EndianS16_BtoN(tempRect.right);
  287.             tempRect.bottom = EndianS16_BtoN(tempRect.bottom);
  288.             DrawPicture(gMonitorPICT, &tempRect);
  289.  
  290.             PrClosePage (printPort);
  291.             err = PrError();
  292.             PrCloseDoc (printPort);
  293.             err = PrError();
  294.             if ((**gPrintRec).prJob.bJDocLoop == bSpoolLoop)
  295.             {
  296.                 PrPicFile (gPrintRec, 0, 0, 0, &printStatus);
  297.                 err = PrError();
  298.             }
  299.         }
  300.         PrClose();
  301.         err = PrError();
  302.         HUnlock((Handle) gMonitorPICT);
  303.     }
  304. }
  305.  
  306. /* ---------------------------------------------------------------------- */
  307.  
  308. void DoCopyToClipboard(void)
  309. {
  310.     ComponentResult    err;
  311.  
  312.     // Copy a frame from the monitor
  313.     if (gMonitorPICT != nil)
  314.         KillPicture (gMonitorPICT);
  315.     gMonitorPICT = nil;
  316.     err = SGGrabPict (gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
  317.     if ((err == noErr) && (gMonitorPICT != nil))
  318.     {
  319.         err = ZeroScrap();
  320.         HLock ((Handle) gMonitorPICT);
  321.         err = PutScrap (GetHandleSize ((Handle) gMonitorPICT), 'PICT', *(Handle)gMonitorPICT);
  322.         HUnlock ((Handle) gMonitorPICT);
  323.     }
  324. }
  325.  
  326. /* ---------------------------------------------------------------------- */
  327.  
  328. static pascal Boolean
  329. SeqGrabberModalFilterProc (DialogPtr theDialog, EventRecord *theEvent,
  330.     short *itemHit, long refCon)
  331. {
  332.     // Ordinarily, if we had multiple windows we cared about, we'd handle
  333.     // updating them in here, but since we don't, we'll just clear out
  334.     // any update events meant for us
  335.     
  336.     Boolean    handled = false;
  337.     
  338.     if ((theEvent->what == updateEvt) && 
  339.         ((WindowPtr) theEvent->message == (WindowPtr) refCon))
  340.     {
  341.         WindowPtr    wPtr = (WindowPtr) refCon;
  342.         BeginUpdate (wPtr);
  343.         EndUpdate (wPtr);
  344.         handled = true;
  345.     }
  346.     return (handled);
  347. }
  348.  
  349. /* ---------------------------------------------------------------------- */
  350.  
  351. void DoVideoSettings(void)
  352. {
  353.     Rect    newActiveVideoRect;
  354.     Rect    adjustedActiveVideoRect;
  355.     Rect    curBounds, curVideoRect, newVideoRect, newBounds;
  356.     short    width, height;
  357.     ComponentResult    err;
  358.     GrafPtr    savedPort;
  359.     RgnHandle    deadRgn;
  360.     SGModalFilterUPP    seqGragModalFilterUPP;
  361.     
  362.     // Get our current state
  363.     err = SGGetChannelBounds (gVideoChannel, &curBounds);
  364.     err = SGGetVideoRect (gVideoChannel, &curVideoRect);
  365.     
  366.     // Pause
  367.     err = SGPause (gSeqGrabber, true);
  368.     
  369.     // Do the dialog thang
  370.     seqGragModalFilterUPP = (SGModalFilterUPP)NewSGModalFilterProc(SeqGrabberModalFilterProc);
  371.     err = SGSettingsDialog(gSeqGrabber, gVideoChannel, 0, 
  372.         nil, 0L, seqGragModalFilterUPP, (long)StripAddress ((Ptr) gMonitor));
  373.     DisposeRoutineDescriptor(seqGragModalFilterUPP);
  374.     
  375.     // What happened?
  376.     err = SGGetVideoRect (gVideoChannel, &newVideoRect);
  377.     err = SGGetSrcVideoBounds (gVideoChannel, &newActiveVideoRect);
  378.  
  379.     // Set up our port
  380.     GetPort (&savedPort);
  381.     MacSetPort (gMonitor);
  382.     
  383.     // Has our active rect changed?
  384.     // If so, it's because our video standard changed (e.g., NTSC to PAL),
  385.     // and we need to adjust our monitor window
  386.     if (!MacEqualRect (&gActiveVideoRect, &newActiveVideoRect))
  387.     {
  388.         if (gFullSize)
  389.         {
  390.             width = newActiveVideoRect.right - newActiveVideoRect.left;
  391.             height = newActiveVideoRect.bottom - newActiveVideoRect.top;
  392.             
  393.             gActiveVideoRect = newActiveVideoRect;
  394.             SizeWindow (gMonitor, width, height, false);
  395.             err = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
  396.         }
  397.         else if (gHalfSize)
  398.         {
  399.             width = (newActiveVideoRect.right - newActiveVideoRect.left) / 2;
  400.             height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 2;
  401.             
  402.             gActiveVideoRect = newActiveVideoRect;
  403.             SizeWindow (gMonitor, width, height, false);
  404.             err = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
  405.         }
  406.         else if (gQuarterSize)
  407.         {
  408.             width = (newActiveVideoRect.right - newActiveVideoRect.left) / 4;
  409.             height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 4;
  410.             
  411.             gActiveVideoRect = newActiveVideoRect;
  412.             SizeWindow (gMonitor, width, height, false);
  413.             err = SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
  414.         }
  415.     }
  416.     
  417.     // Has our crop changed?
  418.     // This code shows how to be crop video panel friendly
  419.     // Two important things - 
  420.     // 1) Be aware that you might have been cropped and adjust your
  421.     //    video window appropriately
  422.     // 2) Be aware that you might have been adjusted and attempt to
  423.     //    account for this.  Adjusting refers to using the digitizer
  424.     //    rect to "adjust" the active source rect within the maximum
  425.     //    source rect.  This is useful if you're getting those nasty
  426.     //    black bands on the sides of your video display - you can use
  427.     //    the control-arrow key sequence to shift the active source 
  428.     //    rect around when you're in the crop video panel
  429.     
  430.     adjustedActiveVideoRect = gActiveVideoRect;
  431.     if (!MacEqualRect (&curVideoRect, &newVideoRect))
  432.     {
  433.         if ((newVideoRect.left < gActiveVideoRect.left) ||
  434.             (newVideoRect.right > gActiveVideoRect.right) ||
  435.             (newVideoRect.top < gActiveVideoRect.top) ||
  436.             (newVideoRect.bottom > gActiveVideoRect.bottom))
  437.         {
  438.             if (newVideoRect.left < gActiveVideoRect.left)
  439.             {
  440.                 adjustedActiveVideoRect.left = newVideoRect.left;
  441.                 adjustedActiveVideoRect.right -= (gActiveVideoRect.left - newVideoRect.left);
  442.             }
  443.             if (newVideoRect.right > gActiveVideoRect.right)
  444.             {
  445.                 adjustedActiveVideoRect.right = newVideoRect.right;
  446.                 adjustedActiveVideoRect.left += (newVideoRect.right - gActiveVideoRect.right);
  447.             }
  448.             if (newVideoRect.top < gActiveVideoRect.top)
  449.             {
  450.                 adjustedActiveVideoRect.top = newVideoRect.top;
  451.                 adjustedActiveVideoRect.bottom -= (gActiveVideoRect.top - newVideoRect.top);
  452.             }
  453.             if (newVideoRect.bottom > gActiveVideoRect.bottom)
  454.             {
  455.                 adjustedActiveVideoRect.bottom = newVideoRect.bottom;
  456.                 adjustedActiveVideoRect.top += (newVideoRect.bottom - gActiveVideoRect.bottom);
  457.             }
  458.             newBounds = newVideoRect;
  459.             MapRect (&newBounds, &adjustedActiveVideoRect, &(gMonitor->portRect));
  460.         }
  461.         else    // Can't tell if we've been adjusted (digitizer rect is smaller on all sides
  462.                 // than the active source rect)
  463.         {
  464.             newBounds = newVideoRect;
  465.             MapRect (&newBounds, &gActiveVideoRect, &(gMonitor->portRect));
  466.         }
  467.         width = newBounds.right - newBounds.left;
  468.         height = newBounds.bottom - newBounds.top;
  469.         err = SGSetChannelBounds (gVideoChannel, &newBounds);
  470.     }
  471.  
  472.     // Clean out the part of the port that isn't being drawn in
  473.     deadRgn = NewRgn();
  474.     if (deadRgn != nil)
  475.     {
  476.         Rect    boundsRect;
  477.         err = SGGetChannelBounds (gVideoChannel, &boundsRect);
  478.         err = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
  479.         EraseRgn (deadRgn);
  480.         DisposeRgn (deadRgn);
  481.     }
  482.  
  483.     MacSetPort (savedPort);
  484.     
  485. #if !TARGET_OS_MAC
  486.     // This is necessary, for now, to get the grab to start again afer the
  487.     // dialog goes away.  For some reason the video destRect never gets reset to point
  488.     // back to the monitor window.
  489.     SGSetChannelBounds (gVideoChannel, &(gMonitor->portRect));
  490. #endif
  491.  
  492.     // The pause that refreshes
  493.     err = SGPause (gSeqGrabber, false);
  494. }
  495.  
  496. /* ---------------------------------------------------------------------- */
  497.  
  498. void DoSoundSettings(void)
  499. {
  500.     SGModalFilterUPP    seqGragModalFilterUPP;
  501.     ComponentResult        err;
  502.  
  503.     seqGragModalFilterUPP = (SGModalFilterUPP)NewSGModalFilterProc(SeqGrabberModalFilterProc);
  504.     err = SGSettingsDialog (gSeqGrabber, gSoundChannel, 0,
  505.         nil, 0L, seqGragModalFilterUPP, (long) StripAddress ((Ptr) gMonitor));
  506.     DisposeRoutineDescriptor(seqGragModalFilterUPP);
  507. }
  508.  
  509. /* ---------------------------------------------------------------------- */
  510.  
  511. void DoResize(short divisor)
  512. {
  513.     short        width, height;
  514.     GrafPtr        savedPort;
  515.     Rect        curBounds, maxBoundsRect;
  516.     RgnHandle    deadRgn;
  517.     ComponentResult    err;
  518.  
  519.     // New width and height
  520.     width = (gActiveVideoRect.right - gActiveVideoRect.left) / divisor;
  521.     height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / divisor;
  522.     
  523.     gQuarterSize = (divisor == 4 ? true : false);
  524.     gHalfSize = (divisor == 2 ? true : false);
  525.     gFullSize = (divisor == 1 ? true : false);
  526.     
  527.     // Resize the monitor
  528.     GetPort (&savedPort);
  529.     MacSetPort (gMonitor);
  530.     err = SGPause (gSeqGrabber, true);
  531.     err = SGGetChannelBounds (gVideoChannel, &curBounds);
  532.     maxBoundsRect = gMonitor->portRect;
  533.     SizeWindow (gMonitor, width, height, false);
  534.     MapRect (&curBounds, &maxBoundsRect, &(gMonitor->portRect));
  535.     err = SGSetChannelBounds (gVideoChannel, &curBounds);
  536.  
  537.     // Clean out part of port we're not drawing in
  538.     deadRgn = NewRgn();
  539.     if (deadRgn != nil)
  540.     {
  541.         Rect    boundsRect;
  542.  
  543.         err = SGGetChannelBounds (gVideoChannel, &boundsRect);
  544.         err = XorRectToRgn (&boundsRect, &(gMonitor->portRect), &deadRgn);
  545.         EraseRgn (deadRgn);
  546.         DisposeRgn (deadRgn);
  547.     }
  548.         
  549.     MacSetPort (savedPort);
  550.     err = SGPause (gSeqGrabber, false);
  551. }
  552.  
  553. /* ---------------------------------------------------------------------- */
  554.  
  555. static OSErr XorRectToRgn (Rect *srcRectA, Rect *srcRectB, RgnHandle *destRgn)
  556. {
  557.     RgnHandle    srcRgnA = NewRgn();
  558.     RgnHandle    srcRgnB = NewRgn();
  559.     OSErr        result = noErr;
  560.     
  561.     if ((destRgn != nil) && (*destRgn != nil))
  562.     {
  563.         if ((srcRgnA != nil) &&
  564.             (srcRgnB != nil))
  565.         {
  566.             RectRgn (srcRgnA, srcRectA);
  567.             RectRgn (srcRgnB, srcRectB);
  568.             MacXorRgn (srcRgnA, srcRgnB, *destRgn);
  569.             DisposeRgn (srcRgnA);
  570.             DisposeRgn (srcRgnB);
  571.         }
  572.         else
  573.         {
  574.             result = memFullErr;
  575.         }
  576.     }
  577.     else
  578.     {
  579.         result = nilHandleErr;
  580.     }
  581.     return (result);
  582. }
  583.  
  584. /* ---------------------------------------------------------------------- */
  585.